#ifndef __VISUALOSC_H__
#define __VISUALOSC_H__


#include <stdint.h>
#include "export_c.h"
#include "plat/nonecopyable.h"

#define VISUAL_OSC_UART_PORT_ID 0
#define NIMING_TEMP_BUFFER_SIZE 256

/// @brief 虚拟示波器
class VisualOsc : public NoneCopyable
{
public:
    static void SetEnabled(bool enabled);

    //匿名地面工作站  
    static void NimingOldReportIMUAngle(int16_t rol, int16_t pit, int16_t yaw, uint32_t alt, uint8_t fly_mode, uint8_t armed);
    static void NimingOldReportIMU(int16_t  acc_x, int16_t  acc_y, int16_t  acc_z,
                                    int16_t gyro_x, int16_t gyro_y, int16_t gyro_z,
                                    int16_t  mag_x, int16_t  mag_y, int16_t  mag_z);

    //通过灵活数据帧发送 [匿名助手], 和地面工作站 不是一个软件
    static void NimingSendCurveBuffer(int ch, uint8_t *buf, int len);
    
    //发送到同一通道的 子列表
    template<typename... Args>
    static void NimingSendCurveChSubList(int ch, const Args&... args)
    {
        if(sizeof...(args) == 0)
            return;

        m_bufferLen = 0;
        __NimingSendCurveChSubList(args...);
        NimingSendCurveBuffer(ch, m_buffer, m_bufferLen);
    }

    //依次0,1,2...
    //发送到不同ch，性能较低些
    template<typename... Args>
    static void NimingSendCurve(const Args&... args)
    {
        int ch = 0;
        __NimingSendCurveChAutoAdd(ch, args...);
    }

    //山外助手
    static void ShangwaiSendCurve(uint8_t *buf, int len);

    //山外助手
    template<typename... Args>
    static void ShangwaiSendCurve(const Args&... args)
    {
        ShangwaiSendHead();
        __ShangwaiSendCurve(args...);
        ShangwaiSendTail(); 
    }

    //serial_port_plotter
    static void PlotterSendCurve(const std::string& line);

private:
    static void WriteToStream(const uint8_t *buf, int len);
    ///旧版本的匿名工作站
    static void NimingOldReportBuffer(uint8_t cmd, uint8_t *dat, uint8_t len);

    template<typename T>
    static void __NimingSendCurveChSubList(T t)
    {
        memcpy(m_buffer + m_bufferLen, (uint8_t*)&t, sizeof(T));
        m_bufferLen += sizeof(T);
    }

    template<typename T, typename... Args>
    static void __NimingSendCurveChSubList(T t, const Args&... args)
    {
        __NimingSendCurveChSubList(t);
        __NimingSendCurveChSubList(args...);
    }

    template<typename T>
    static void __NimingSendCurveChAutoAdd(int &ch, T t)
    {
        NimingSendCurveBuffer(ch++, (uint8_t*)&t, sizeof(T));
    }

    template<typename T, typename... Args>
    static void __NimingSendCurveChAutoAdd(int &ch, T t, const Args&... args)
    {
        __NimingSendCurveChAutoAdd(ch, t);
        __NimingSendCurveChAutoAdd(ch, args...);
    }

    template<class T>
    static void __ShangwaiSendCurve(const T& t)
    {
        WriteToStream((uint8_t*)&t, sizeof(T));
    }

    template<class T, class ...Args>
    static void __ShangwaiSendCurve(const T& t, const Args&... args)
    {
        WriteToStream((uint8_t*)&t, sizeof(T));
        __ShangwaiSendCurve(args...);   
    }

    static void ShangwaiSendHead();
    static void ShangwaiSendTail();

private:
    static uint8_t m_buffer[NIMING_TEMP_BUFFER_SIZE];
    static int m_bufferLen;
    static bool m_enabled;
};

#endif // __VISUALOSC_H__
